<template>
  <div class="threejs-container">
    <div ref="container" class="threejs-canvas"></div>
    <div class="threejs-overlay">
      <div class="loading" v-if="loading">
        <a-spin size="large" />
        <div class="loading-text">{{ loadingText }}</div>
        <div class="loading-progress" v-if="loadingProgress > 0">
          <a-progress 
            :percent="loadingProgress" 
            size="small" 
            :show-text="false"
            stroke-color="linear-gradient(90deg, #4facfe 0%, #00f2fe 100%)"
          />
          <div class="progress-text">{{ Math.round(loadingProgress) }}%</div>
        </div>
      </div>
      
      <!-- 模型控制面板 -->
      <div class="model-controls" v-if="!loading && model">
        <a-button-group size="small">
          <a-button @click="resetCamera" type="outline">
            <template #icon><icon-refresh /></template>
            重置视角
          </a-button>
          <a-button @click="toggleWireframe" type="outline">
            <template #icon><icon-eye /></template>
            {{ showWireframe ? '实体' : '线框' }}
          </a-button>
          <a-button @click="toggleAnimation" type="outline" v-if="animations.length > 0">
            <template #icon><icon-play-arrow v-if="!isAnimating" /><icon-pause v-else /></template>
            {{ isAnimating ? '暂停' : '播放' }}
          </a-button>
          <a-button @click="togglePerformanceMonitor" type="outline">
            <template #icon><icon-computer /></template>
            性能
          </a-button>
        </a-button-group>
      </div>
      
      <!-- 缓存状态指示器 - 暂时隐藏 -->
      <!-- <div class="cache-info" v-if="!loading">
        <a-tooltip content="模型缓存状态">
          <div class="cache-indicator" :class="{ 'cached': isModelCached }">
            <icon-database />
          </div>
        </a-tooltip>
      </div> -->
    </div>
    
    <!-- 性能监控组件 -->
    <ModelPerformanceMonitor 
      ref="performanceMonitor"
      :visible="showPerformanceMonitor"
    />
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, computed, watch } from 'vue'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
import modelCache from '../utils/modelCache'
import stlLoader from '../utils/stlLoader'
import { useGlobalModelPreloader } from '../composables/useModelPreloader'
import ModelPerformanceMonitor from './ModelPerformanceMonitor.vue'

// Props
const props = defineProps({
  modelPath: {
    type: String,
    default: null
  }
})

// 响应式状态
const container = ref(null)
const loading = ref(true)
const loadingText = ref('初始化3D场景...')
const loadingProgress = ref(0)
const model = ref(null)
const isModelCached = ref(false)
const showWireframe = ref(false)
const isAnimating = ref(false)
const animations = ref([])
const showPerformanceMonitor = ref(false)

// ThreeJS 对象
let scene, camera, renderer, controls, clock
let animationId = null
let animationMixer = null
let currentAnimationAction = null

// 组件引用
const performanceMonitor = ref(null)

// 默认模型路径
const DEFAULT_MODEL_PATH = '/mox.glb'

// 使用全局预加载器
const preloader = useGlobalModelPreloader()

// 计算属性
const cacheInfo = computed(() => modelCache.getCacheInfo())
const currentModelPath = computed(() => props.modelPath || DEFAULT_MODEL_PATH)

// 监听模型路径变化
watch(() => props.modelPath, async (newPath) => {
  if (newPath && scene) {
    await loadCurrentModel()
  }
}, { immediate: false })

// 监听预加载状态
watch(() => preloader.preloadState.isPreloading, (isPreloading) => {
  if (isPreloading && loading.value) {
    loadingText.value = '模型预加载中...'
  }
})

watch(() => preloader.preloadState.preloadProgress, (progress) => {
  if (preloader.preloadState.isPreloading && loading.value) {
    loadingProgress.value = progress
    loadingText.value = `模型预加载中... ${Math.round(progress)}%`
  }
})

const initThreeJS = async () => {
  loadingText.value = '初始化3D场景...'
  
  // 创建场景
  scene = new THREE.Scene()
  scene.background = new THREE.Color(0xffffff)
  scene.fog = new THREE.Fog(0xffffff, 100, 1000) // 添加雾效
  
  // 创建相机
  camera = new THREE.PerspectiveCamera(
    45,
    container.value.clientWidth / container.value.clientHeight,
    0.1,
    2000
  )
  camera.position.set(10, 10, 10) // 调整默认相机位置以适应模型
  
  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ 
    antialias: true, 
    alpha: true,
    powerPreference: "high-performance"
  })
  renderer.setSize(container.value.clientWidth, container.value.clientHeight)
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
  renderer.shadowMap.enabled = true
  renderer.shadowMap.type = THREE.PCFSoftShadowMap
  renderer.outputColorSpace = THREE.SRGBColorSpace
  renderer.toneMapping = THREE.ACESFilmicToneMapping
  renderer.toneMappingExposure = 1.2
  container.value.appendChild(renderer.domElement)
  
  // 添加轨道控制器
  controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true
  controls.dampingFactor = 0.05
  controls.screenSpacePanning = false
  controls.minDistance = 5
  controls.maxDistance = 200
  controls.maxPolarAngle = Math.PI * 0.9
  controls.autoRotate = false
  controls.autoRotateSpeed = 0.5
  
  // 添加光源
  setupLighting()
  
  // // 创建地面
  // createGround()
  
  // 时钟
  clock = new THREE.Clock()
  
  // 加载当前模型
  await loadCurrentModel()
  
  // 开始动画
  animate()
  
  // 窗口大小调整
  window.addEventListener('resize', onWindowResize)
}

// 设置全局光照
const setupLighting = () => {
  // 强环境光 - 提供基础全局照明
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.5)
  scene.add(ambientLight)
  
  // 半球光 - 模拟天空和地面的反射光
  const hemisphereLight = new THREE.HemisphereLight(0x87ceeb, 0x404040, 0.6)
  scene.add(hemisphereLight)
  
  // 多方向点光源 - 提供均匀的全方位照明
  const pointLight1 = new THREE.PointLight(0xffffff, 0.4, 200)
  pointLight1.position.set(50, 50, 50)
  scene.add(pointLight1)
  
  const pointLight2 = new THREE.PointLight(0xffffff, 0.4, 200)
  pointLight2.position.set(-50, 50, -50)
  scene.add(pointLight2)
  
  const pointLight3 = new THREE.PointLight(0xffffff, 0.4, 200)
  pointLight3.position.set(50, -50, -50)
  scene.add(pointLight3)
  
  const pointLight4 = new THREE.PointLight(0xffffff, 0.4, 200)
  pointLight4.position.set(-50, -50, 50)
  scene.add(pointLight4)
}

// 加载当前模型（根据路径决定加载器）
const loadCurrentModel = async () => {
  // 清理之前的模型
  if (model.value) {
    scene.remove(model.value)
    model.value = null
    animations.value = []
    if (animationMixer) {
      animationMixer.stopAllAction()
      animationMixer = null
    }
    currentAnimationAction = null
    isAnimating.value = false
  }

  const modelPath = currentModelPath.value
  if (!modelPath) {
    loading.value = false
    return
  }

  loading.value = true
  
  try {
    // 根据文件扩展名决定使用哪个加载器
    const extension = modelPath.split('.').pop().toLowerCase()
    
    if (extension === 'stl') {
      await loadSTLModel(modelPath)
    } else if (extension === 'glb' || extension === 'gltf') {
      await loadGLBModel(modelPath)
    } else if (extension === 'fbx') {
      await loadFBXModel(modelPath)
    } else if (extension === 'obj') {
      await loadOBJModel(modelPath)
    } else {
      throw new Error(`不支持的文件格式: ${extension}`)
    }
    
  } catch (error) {
    console.error('模型加载失败:', error)
    loadingText.value = '模型加载失败，使用默认场景'
    createFallbackScene()
  }
  
  setTimeout(() => {
    loading.value = false
  }, 500)
}

// 加载STL模型
const loadSTLModel = async (path) => {
  loadingText.value = '正在加载STL模型...'
  loadingProgress.value = 0
  
  const stlMesh = await stlLoader.loadSTL(path, {
    color: 0x4facfe,
    metalness: 0.3,
    roughness: 0.4,
    onProgress: (percentage, progress) => {
      loadingProgress.value = percentage
      loadingText.value = `加载STL模型... ${Math.round(percentage)}%`
    }
  })
  
  model.value = stlMesh
  scene.add(stlMesh)
  
  // 调整相机位置
  const box = new THREE.Box3().setFromObject(stlMesh)
  const boundingSphere = box.getBoundingSphere(new THREE.Sphere())
  const distance = boundingSphere.radius * 2.5
  camera.position.set(distance, distance * 0.8, distance)
  controls.target.copy(boundingSphere.center)
  controls.update()
  
  loadingText.value = 'STL模型加载完成'
  console.log('STL模型加载成功', stlMesh)
}

// 加载GLB模型
const loadGLBModel = async (path) => {
  try {
    // 检查模型是否已预加载
    const isPreloaded = preloader.isModelPreloaded(path)
    const cacheInfo = modelCache.getCacheInfo()
    isModelCached.value = cacheInfo.cachedModels > 0 || isPreloaded
    
    if (isPreloaded) {
      loadingText.value = '从缓存加载模型...'
    } else {
      loadingText.value = '正在加载GLB模型...'
      loadingProgress.value = 0
    }
    
    const glbModel = await modelCache.loadModel(path, {
      enableLOD: true,
      enableOptimization: true,
      enableCaching: true,
      onProgress: (percentage, progress) => {
        if (!isPreloaded) {
          loadingProgress.value = percentage
          loadingText.value = `加载模型中... ${Math.round(percentage)}%`
        }
      }
    })
    
    // 设置模型
    model.value = glbModel
    
    // 保持模型原始大小和位置，只调整相机
    const box = new THREE.Box3().setFromObject(glbModel)
    
    // 检查动画
    if (glbModel.animations && glbModel.animations.length > 0) {
      animations.value = glbModel.animations.map(anim => ({
        ...anim,
        name: anim.name || '未命名动画'
      }))
      animationMixer = new THREE.AnimationMixer(glbModel)
      
      // 播放第一个动画
      if (animations.value.length > 0) {
        currentAnimationAction = animationMixer.clipAction(animations.value[0])
        currentAnimationAction.play()
        isAnimating.value = true
      }
    }
    
    scene.add(glbModel)
    
    // 更新相机位置
    const boundingSphere = box.getBoundingSphere(new THREE.Sphere())
    const distance = boundingSphere.radius * 0.8
    camera.position.set(distance, distance, distance)
    controls.target.set(0, 0, 0)
    controls.update()
    
    loadingText.value = '模型加载完成'
    setTimeout(() => {
      loading.value = false
    }, 500)
    
    console.log('GLB模型加载成功', glbModel)
    
  } catch (error) {
    console.error('GLB模型加载失败:', error)
    console.error('错误详情:', error.message)
    console.error('错误堆栈:', error.stack)
    loadingText.value = '模型加载失败，使用默认场景'
    
    // 回退到默认的box
    createFallbackScene()
    
    setTimeout(() => {
      loading.value = false
    }, 1000)
  }
}

// 加载FBX模型
const loadFBXModel = async (path) => {
  loadingText.value = '正在加载FBX模型...'
  loadingProgress.value = 0
  
  return new Promise((resolve, reject) => {
    const loader = new FBXLoader()
    
    loader.load(
      path,
      (fbxModel) => {
        try {
          model.value = fbxModel
          
          // 设置材质和阴影
          fbxModel.traverse((child) => {
            if (child.isMesh) {
              child.castShadow = true
              child.receiveShadow = true
              
              // 确保材质正确设置
              if (child.material) {
                if (Array.isArray(child.material)) {
                  child.material.forEach(mat => {
                    if (mat.isMeshStandardMaterial || mat.isMeshPhongMaterial) {
                      mat.needsUpdate = true
                    }
                  })
                } else {
                  if (child.material.isMeshStandardMaterial || child.material.isMeshPhongMaterial) {
                    child.material.needsUpdate = true
                  }
                }
              }
            }
          })
          
          // 计算边界框并调整相机
          const box = new THREE.Box3().setFromObject(fbxModel)
          const center = box.getCenter(new THREE.Vector3())
          const size = box.getSize(new THREE.Vector3())
          
          // 居中模型
          fbxModel.position.x = -center.x
          fbxModel.position.y = -box.min.y
          fbxModel.position.z = -center.z
          
          // 自动缩放适配
          const maxDim = Math.max(size.x, size.y, size.z)
          if (maxDim > 10) {
            const scale = 10 / maxDim
            fbxModel.scale.setScalar(scale)
          } else if (maxDim < 1) {
            const scale = 2 / maxDim
            fbxModel.scale.setScalar(scale)
          }
          
          // 检查动画
          if (fbxModel.animations && fbxModel.animations.length > 0) {
            animations.value = fbxModel.animations.map(anim => ({
              ...anim,
              name: anim.name || '未命名动画'
            }))
            animationMixer = new THREE.AnimationMixer(fbxModel)
            
            // 播放第一个动画
            if (animations.value.length > 0) {
              currentAnimationAction = animationMixer.clipAction(animations.value[0])
              currentAnimationAction.play()
              isAnimating.value = true
            }
          }
          
          scene.add(fbxModel)
          
          // 调整相机位置
          const boundingSphere = box.getBoundingSphere(new THREE.Sphere())
          const distance = boundingSphere.radius * 2.5
          camera.position.set(distance, distance * 0.8, distance)
          controls.target.copy(boundingSphere.center)
          controls.update()
          
          loadingText.value = 'FBX模型加载完成'
          console.log('FBX模型加载成功', fbxModel)
          resolve()
        } catch (error) {
          console.error('FBX模型处理失败:', error)
          reject(error)
        }
      },
      (progress) => {
        if (progress.lengthComputable) {
          const percentage = (progress.loaded / progress.total) * 100
          loadingProgress.value = percentage
          loadingText.value = `加载FBX模型... ${Math.round(percentage)}%`
        }
      },
      (error) => {
        console.error('FBX模型加载失败:', error)
        reject(error)
      }
    )
  })
}

// 加载OBJ模型
const loadOBJModel = async (path) => {
  loadingText.value = '正在加载OBJ模型...'
  loadingProgress.value = 0
  
  return new Promise((resolve, reject) => {
    const loader = new OBJLoader()
    
    loader.load(
      path,
      (objModel) => {
        try {
          model.value = objModel
          
          // 设置默认材质和阴影
          objModel.traverse((child) => {
            if (child.isMesh) {
              child.castShadow = true
              child.receiveShadow = true
              
              // 为OBJ模型设置默认材质（因为OBJ文件通常不包含材质信息）
              if (!child.material || child.material.type === 'MeshBasicMaterial') {
                child.material = new THREE.MeshPhongMaterial({
                  color: 0x4facfe,
                  shininess: 100,
                  specular: 0x222222
                })
              }
              
              // 确保材质正确设置
              if (child.material) {
                if (Array.isArray(child.material)) {
                  child.material.forEach(mat => {
                    mat.needsUpdate = true
                  })
                } else {
                  child.material.needsUpdate = true
                }
              }
            }
          })
          
          // 计算边界框并调整相机
          const box = new THREE.Box3().setFromObject(objModel)
          const center = box.getCenter(new THREE.Vector3())
          const size = box.getSize(new THREE.Vector3())
          
          // 居中模型
          objModel.position.x = -center.x
          objModel.position.y = -box.min.y
          objModel.position.z = -center.z
          
          // 自动缩放适配
          const maxDim = Math.max(size.x, size.y, size.z)
          if (maxDim > 10) {
            const scale = 10 / maxDim
            objModel.scale.setScalar(scale)
          } else if (maxDim < 1) {
            const scale = 2 / maxDim
            objModel.scale.setScalar(scale)
          }
          
          scene.add(objModel)
          
          // 调整相机位置
          const boundingSphere = box.getBoundingSphere(new THREE.Sphere())
          const distance = boundingSphere.radius * 2.5
          camera.position.set(distance, distance * 0.8, distance)
          controls.target.copy(boundingSphere.center)
          controls.update()
          
          loadingText.value = 'OBJ模型加载完成'
          console.log('OBJ模型加载成功', objModel)
          resolve()
        } catch (error) {
          console.error('OBJ模型处理失败:', error)
          reject(error)
        }
      },
      (progress) => {
        if (progress.lengthComputable) {
          const percentage = (progress.loaded / progress.total) * 100
          loadingProgress.value = percentage
          loadingText.value = `加载OBJ模型... ${Math.round(percentage)}%`
        }
      },
      (error) => {
        console.error('OBJ模型加载失败:', error)
        reject(error)
      }
    )
  })
}

// 创建回退场景（当模型加载失败时）
const createFallbackScene = () => {
  const boxGeometry = new THREE.BoxGeometry(10, 10, 10)
  const boxMaterial = new THREE.MeshPhongMaterial({ 
    color: 0x4facfe,
    transparent: true,
    opacity: 0.8
  })
  const box = new THREE.Mesh(boxGeometry, boxMaterial)
  box.position.set(0, 5, 0)
  box.castShadow = true
  box.receiveShadow = true
  scene.add(box)
  
  // 添加边框
  const edges = new THREE.EdgesGeometry(boxGeometry)
  const lineMaterial = new THREE.LineBasicMaterial({ color: 0x00f2fe })
  const wireframe = new THREE.LineSegments(edges, lineMaterial)
  wireframe.position.set(0, 5, 0)
  scene.add(wireframe)
}


// 控制方法
const resetCamera = () => {
  if (model.value) {
    const box = new THREE.Box3().setFromObject(model.value)
    const boundingSphere = box.getBoundingSphere(new THREE.Sphere())
    const distance = boundingSphere.radius * 0.2
    
    camera.position.set(distance, distance * 0.8, distance)
    camera.lookAt(boundingSphere.center)
    controls.target.copy(boundingSphere.center)
    controls.update()
  } else {
    camera.position.set(10, 10, 10)
    camera.lookAt(0, 0, 0)
    controls.target.set(0, 0, 0)
    controls.update()
  }
}

const toggleWireframe = () => {
  showWireframe.value = !showWireframe.value
  
  if (model.value) {
    model.value.traverse((child) => {
      if (child.isMesh && child.material) {
        const materials = Array.isArray(child.material) ? child.material : [child.material]
        materials.forEach(material => {
          material.wireframe = showWireframe.value
        })
      }
    })
  }
}

const toggleAnimation = () => {
  if (!animationMixer || !currentAnimationAction) return
  
  if (isAnimating.value) {
    currentAnimationAction.paused = true
    isAnimating.value = false
  } else {
    currentAnimationAction.paused = false
    isAnimating.value = true
  }
}

const togglePerformanceMonitor = () => {
  showPerformanceMonitor.value = !showPerformanceMonitor.value
  if (performanceMonitor.value) {
    if (showPerformanceMonitor.value) {
      performanceMonitor.value.show()
    } else {
      performanceMonitor.value.hide()
    }
  }
}

const animate = () => {
  try {
    animationId = requestAnimationFrame(animate)
    
    const delta = clock.getDelta()
    
    // 更新动画混合器
    if (animationMixer) {
      animationMixer.update(delta)
    }
    
    // 更新控制器
    if (controls) {
      controls.update()
    }
    
    // 渲染场景
    if (renderer && scene && camera) {
      renderer.render(scene, camera)
    }
  } catch (error) {
    console.error('动画循环错误:', error)
    console.error('错误堆栈:', error.stack)
    // 停止动画循环以防止错误重复
    if (animationId) {
      cancelAnimationFrame(animationId)
    }
  }
}

const onWindowResize = () => {
  if (container.value && camera && renderer) {
    camera.aspect = container.value.clientWidth / container.value.clientHeight
    camera.updateProjectionMatrix()
    renderer.setSize(container.value.clientWidth, container.value.clientHeight)
  }
}

onMounted(async () => {
  await initThreeJS()
})

onUnmounted(() => {
  // 清理动画
  if (animationId) {
    cancelAnimationFrame(animationId)
  }
  
  // 清理动画混合器
  if (animationMixer) {
    animationMixer.stopAllAction()
    animationMixer.uncacheRoot(animationMixer.getRoot())
  }
  
  // 清理场景
  if (scene) {
    scene.traverse((child) => {
      if (child.isMesh) {
        if (child.geometry) {
          child.geometry.dispose()
        }
        if (child.material) {
          const materials = Array.isArray(child.material) ? child.material : [child.material]
          materials.forEach(material => material.dispose())
        }
      }
    })
    scene.clear()
  }
  
  // 清理渲染器
  if (renderer) {
    renderer.dispose()
    renderer.forceContextLoss()
  }
  
  // 清理控制器
  if (controls) {
    controls.dispose()
  }
  
  // 移除事件监听器
  window.removeEventListener('resize', onWindowResize)
  
  console.log('ThreeJS 组件已清理')
})
</script>

<style scoped>
.threejs-container {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 8px;
  overflow: hidden;
}

.threejs-canvas {
  width: 100%;
  height: 100%;
}

.threejs-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  background: rgba(0, 0, 0, 0.8);
  padding: 32px;
  border-radius: 12px;
  backdrop-filter: blur(15px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
  min-width: 300px;
}

.loading-text {
  color: #e8f4fd;
  font-size: 14px;
  font-weight: 500;
  text-align: center;
}

.loading-progress {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.progress-text {
  color: #b8c5d1;
  font-size: 12px;
  text-align: center;
}

.model-controls {
  position: absolute;
  top: 20px;
  right: 20px;
  pointer-events: auto;
  /* background: rgba(0, 0, 0, 0.6); */
  backdrop-filter: blur(10px);
  border-radius: 8px;
  padding: 8px;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.cache-info {
  position: absolute;
  bottom: 20px;
  right: 20px;
  pointer-events: auto;
}

.cache-indicator {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #b8c5d1;
  transition: all 0.3s ease;
  cursor: pointer;
}

.cache-indicator:hover {
  background: rgba(0, 0, 0, 0.8);
  transform: scale(1.1);
}

.cache-indicator.cached {
  color: #4facfe;
  border-color: #4facfe;
  box-shadow: 0 0 10px rgba(79, 172, 254, 0.3);
}

/* 响应式设计 */
@media (max-width: 768px) {
  .model-controls {
    top: 10px;
    right: 10px;
    left: 10px;
    display: flex;
    justify-content: center;
  }
  
  .cache-info {
    bottom: 10px;
    right: 10px;
  }
  
  .loading {
    padding: 24px;
    min-width: 280px;
    margin: 20px;
  }
}

/* 动画效果 */
@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.model-controls,
.cache-info {
  animation: fadeIn 0.5s ease-out;
}
</style>
